<template>
	<view>

		<!-- <view class="layout_horizontal">
			<button class="button_sp" @tap="gotosetuuid" style="flex:1">设置UUID</button>
			<view class="div" style="background-color:white"></view>
			<button class="button_sp" @tap="gotoabout" style="flex:1">关于我们</button>
		</view> -->

		<button :loading="misScanding" class="button_sp" @tap="openBluetoothAdapter">{{scandbutName}}</button>
		<view style="background-color: #fff;height: 10px;width: 100%;"></view>

		<view class="devices_summary">已发现 {{devices.length}} 个BLE设备：</view>
		<scroll-view class="device_list" scroll-y scroll-with-animation>
			<view v-for="(device, index) in devices" :key="index" @tap="gotoComm(device)" class="device_item">
				<view style="font-size: 16px; color: #111;">{{device.name}}</view>
				<view style="font-size: 12px;color: #555;">RSSI: {{device.RSSI}}dBm</view>
				<view style="font-size: 12px;color: #555;">{{device.deviceId}}</view>
			</view>
		</scroll-view>

		<view class="connected_info" v-if="connected">
			<view>
				<text>已连接到 {{name}}</text>
				<view class="operation">
					<button v-if="canWrite" size="mini" @tap="writeBLECharacteristicValue">写数据</button>
					<button size="mini" @tap="closeBLEConnection">断开连接</button>
				</view>
			</view>
			<view v-for="(ch, index) in chs" :key="index" style="font-size: 12px; margin-top: 10px;">
				<view>特性UUID: {{ch.uuid}}</view>
				<view>特性值: {{ch.value}}</view>
			</view>
		</view>
	</view>

</template>

<script>
	export default {
		data() {
			return {
				devices: [],
				connected: false,
				chs: [],
				misScanding: false,
				scandbutName: "搜索蓝牙设备",
				_discoveryStarted: false,
				_deviceId: '',
				_serviceId: '',
				_characteristicId: '',
				name: '',
				canWrite: false
			}
		},
		methods: {
			inArray(arr, key, val) {
				for (let i = 0; i < arr.length; i++) {
					if (arr[i][key] === val) {
						return i;
					}
				}
				return -1;
			},
			ab2hex(buffer) {
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('');
			},
			openBluetoothAdapter() {
				this.misScanding = false;
				uni.openBluetoothAdapter({
					success: (res) => {
						console.log('openBluetoothAdapter success', res);
						this.startBluetoothDevicesDiscovery();
					},
					fail: (res) => {
						if (res.errCode === 10001) {
							uni.onBluetoothAdapterStateChange((res) => {
								console.log('onBluetoothAdapterStateChange', res);
								if (res.available) {
									this.startBluetoothDevicesDiscovery();
								}
							})
						}
					}
				})
			},
			getBluetoothAdapterState() {
				uni.getBluetoothAdapterState({
					success: (res) => {
						console.log('getBluetoothAdapterState', res);
						if (res.discovering) {
							this.onBluetoothDeviceFound();
						} else if (res.available) {
							this.startBluetoothDevicesDiscovery();
						}
					}
				})
			},
			startBluetoothDevicesDiscovery() {
				if (this._discoveryStarted) {
					this.stopBluetoothDevicesDiscovery();
					return;
				}
				this.misScanding = true;
				this.scandbutName = "正在搜索，点击停止";
				this.devices = [];
				this.chs = [];
				this._discoveryStarted = true;
				uni.startBluetoothDevicesDiscovery({
					allowDuplicatesKey: true,
					success: (res) => {
						setTimeout(() => {
							console.log("----BluetoothDevicesDiscovery finish----");
							if (this._discoveryStarted) {
								this.stopBluetoothDevicesDiscovery();
							}
						}, 20000);
						console.log('startBluetoothDevicesDiscovery success', res);
						this.onBluetoothDeviceFound();
					},
				})
			},
			stopBluetoothDevicesDiscovery() {
				this._discoveryStarted = false;
				uni.stopBluetoothDevicesDiscovery();
				this.misScanding = false;
				this.scandbutName = "重新刷新列表";
			},
			onBluetoothDeviceFound() {
				uni.onBluetoothDeviceFound((res) => {
					res.devices.forEach(device => {
						if (!device.name && !device.localName) {
							return;
						}
						const foundDevices = this.devices;
						const idx = this.inArray(foundDevices, 'deviceId', device.deviceId);
						if (idx === -1) {
							this.devices.push(device);
						} else {
							this.devices.splice(idx, 1, device);
						}
					});
				});
			},
			gotoComm(device) {
				console.log("选中的蓝牙设备信息：", device, "\n正在保存当中。。。")
				// 保存选中的蓝牙设备信息到本地
				uni.setStorageSync('selectedDevice', device);
				console.log("保存成功，开始跳转。。。");
				// this.stopBluetoothDevicesDiscovery();//不必等待蓝牙搜索完毕
				uni.navigateTo({
					// url: '/blueTooth/comm/comm'
					url: '/blueTooth/bluetoothBindingPage/bluetoothBindingPage'
				});
			},
			createBLEConnection(device) {
				const deviceId = device.deviceId;
				const name = device.name;
				uni.createBLEConnection({
					deviceId,
					success: (res) => {
						this.connected = true;
						this.name = name;
						this.deviceId = deviceId;
						this.getBLEDeviceServices(deviceId);
					}
				});
				this.stopBluetoothDevicesDiscovery();
			},
			closeBLEConnection() {
				uni.closeBLEConnection({
					deviceId: this.deviceId
				});
				this.connected = false;
				this.chs = [];
				this.canWrite = false;
			},
			getBLEDeviceServices(deviceId) {
				uni.getBLEDeviceServices({
					deviceId,
					success: (res) => {
						for (let i = 0; i < res.services.length; i++) {
							if (res.services[i].isPrimary) {
								this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
								return;
							}
						}
					}
				});
			},
			getBLEDeviceCharacteristics(deviceId, serviceId) {
				uni.getBLEDeviceCharacteristics({
					deviceId,
					serviceId,
					success: (res) => {
						console.log('getBLEDeviceCharacteristics success', res.characteristics);
						for (let i = 0; i < res.characteristics.length; i++) {
							let item = res.characteristics[i];
							if (item.properties.read) {
								uni.readBLECharacteristicValue({
									deviceId,
									serviceId,
									characteristicId: item.uuid,
								});
							}
							if (item.properties.write) {
								this.canWrite = true;
								this._deviceId = deviceId;
								this._serviceId = serviceId;
								this._characteristicId = item.uuid;
								this.writeBLECharacteristicValue();
							}
							if (item.properties.notify || item.properties.indicate) {
								uni.notifyBLECharacteristicValueChange({
									deviceId,
									serviceId,
									characteristicId: item.uuid,
									state: true,
								});
							}
						}
					},
					fail(res) {
						console.error('getBLEDeviceCharacteristics', res);
					}
				});
				// 操作之前先监听，保证第一时间获取数据
				uni.onBLECharacteristicValueChange((characteristic) => {
					const idx = this.inArray(this.chs, 'uuid', characteristic.characteristicId);
					if (idx === -1) {
						this.chs.push({
							uuid: characteristic.characteristicId,
							value: this.ab2hex(characteristic.value)
						});
					} else {
						this.chs.splice(idx, 1, {
							uuid: characteristic.characteristicId,
							value: this.ab2hex(characteristic.value)
						});
					}
				});
			},
			writeBLECharacteristicValue() {
				// 向蓝牙设备发送一个0x00的16进制数据
				let buffer = new ArrayBuffer(1);
				let dataView = new DataView(buffer);
				dataView.setUint8(0, Math.random() * 255 | 0);
				uni.writeBLECharacteristicValue({
					deviceId: this._deviceId,
					serviceId: this._deviceId,
					characteristicId: this._characteristicId,
					value: buffer,
				});
			},
			closeBluetoothAdapter() {
				uni.closeBluetoothAdapter();
				this._discoveryStarted = false;
			},
			gotoabout() {
				uni.navigateTo({
					url: '/pages/about/about'
				});
			},
			gotosetuuid() {
				uni.navigateTo({
					url: '/pages/setuuid/setuuid'
				});
			}
		}
	}
</script>

<style>
	.devices_summary {
		padding: 10px;
		font-size: 16px;
		background-color: hsl(216, 5%, 22%);
		color: #FFF;
		align-items: center;
		justify-content: center;
		display: flex;
	}

	.device_list {
		height: auto;
		margin: 50px 5px;
		margin-top: 5px;
		border: 1px solid #EEE;
		border-radius: 5px;
		width: auto;
	}

	.device_item {
		border-bottom: 1px solid #222;
		padding: 10px;
		color: #666;
	}

	.device_item_hover {
		background-color: rgba(0, 0, 0, .1);
	}

	.connected_info {
		position: fixed;
		bottom: 0;
		width: 100%;
		background-color: #F0F0F0;
		padding: 10px;
		padding-bottom: 20px;
		margin-bottom: env(safe-area-inset-bottom);
		font-size: 14px;
		min-height: 100px;
		box-shadow: 0px 0px 3px 0px;
	}

	.connected_info .operation {
		position: absolute;
		display: inline-block;
		right: 30px;
	}

	.button_sp {
		margin-left: 10px;
		margin-right: 10px;
		margin-top: 5px;
		background-color: #3ba757;
		color: #FFF;
		font-size: 15px;
	}

	.button_sp2 {
		margin-left: 10px;
		margin-right: 10px;
		margin-top: 5px;
		background-color: #757575;
		color: #FFF;
	}

	.flex-wrp {
		height: auto;
		display: flex;
		background-color: #FFFFFF;
	}

	/*横向布局  */
	.layout_horizontal {
		display: flex;
		/*row 横向  column 列表  */
		flex-direction: row;
	}

	/*纵向布局  */
	.layout_vertical {
		height: 100rpx;
		display: flex;
		/*row 横向  column 列表  */
		flex-direction: column;
	}

	/*划线  */
	.line {
		background-color: blue;
		height: 5px;
		width: 100%;
	}

	.div {
		background-color: white;
		height: 10px;
		width: 10px;
	}
</style>